﻿&НаСервере
Процедура ИспользоватьРегламентноеЗадание(Имя, Использовать)
	Задание = РегламентныеЗадания.НайтиПредопределенное(Имя);
	Задание.Использование = Использовать;
	Задание.Записать();
КонецПроцедуры

// Обновляет состояние формы по Режиму агрегатов регистра
&НаСервере
Процедура ОбновитьФорму()
	РежимАгрегатов = РегистрыНакопления.Продажи.ПолучитьРежимАгрегатов();	
	
	// Доступность элементов.
	Элементы.ГруппаОбновления.Доступность = РежимАгрегатов;
	Элементы.ГруппаПерестроение.Доступность = РежимАгрегатов;
	
	// Флажки регламентных заданий.
	РегламентноеПерестроение = РегламентныеЗадания.НайтиПредопределенное("ПерестроениеАгрегатовПродаж").Использование;
	РегламентноеОбновление = РегламентныеЗадания.НайтиПредопределенное("ОбновлениеАгрегатовПродаж").Использование;
	
	// Состояние перестроения.
	Агрегаты = РегистрыНакопления.Продажи.ПолучитьАгрегаты();
	Перестроение = НСтр("ru ='Перестроены: '", "ru") 
		+ Агрегаты.ДатаПостроения 
		+ НСтр("ru ='. Эффект: '", "ru")  
		+ Агрегаты.Эффект
		+ НСтр("ru ='. Размер: '", "ru") 
		+ Агрегаты.Размер 
		+ ".";
КонецПроцедуры

&НаСервере
Процедура ИзменитьРежимАгрегатов()
	// Переключает режим агрегатов. Приводит регистр в рабочее состояние. Переключает регламентные задания, если есть.
	Если РежимАгрегатов Тогда
		// Включение режима агрегатов.
		РегистрыНакопления.Продажи.УстановитьРежимАгрегатов(Истина);
		
		// Перестроение использования агрегатов.
		РегистрыНакопления.Продажи.ПерестроитьИспользованиеАгрегатов();
		
		// Обновление агрегатов (непорционное).
		РегистрыНакопления.Продажи.ОбновитьАгрегаты(Ложь);
	Иначе             
		// Выключение режима агрегатов.
		РегистрыНакопления.Продажи.УстановитьРежимАгрегатов(Ложь);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура РежимАгрегатовПриИзменении(Элемент)
	ИзменитьРежимАгрегатов();
	ОбновитьФорму();	
КонецПроцедуры

&НаСервере
Процедура ОбновитьАгрегаты()
	// Непорционное обновление агрегатов.
	РегистрыНакопления.Продажи.ОбновитьАгрегаты(Ложь);
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьНажатие(Команда)
	Состояние(НСтр("ru ='Подождите!'", "ru") 
		+ Символы.ВК 
		+ НСтр("ru ='Идет обновление агрегатов...'", "ru"));	
	
	ОбновитьАгрегаты();
	
	Состояние(НСтр("ru ='Агрегаты обновлены.'", "ru"));		
КонецПроцедуры

&НаКлиенте
Процедура РегламентноеОбновлениеПриИзменении(Элемент)
	ИспользоватьРегламентноеЗадание("ОбновлениеАгрегатовПродаж", РегламентноеОбновление);
	ОбновитьФорму();	
КонецПроцедуры

&НаСервере
Процедура ПерестроитьИспользованиеАгрегатов()
	РегистрыНакопления.Продажи.ПерестроитьИспользованиеАгрегатов();
КонецПроцедуры

&НаКлиенте
Процедура Перестроить(Команда)
	Состояние(НСтр("ru ='Подождите!'", "ru") 
		+ Символы.ВК 
		+ НСтр("ru ='Идет перестроение использования агрегатов...'", "ru"));	
	
	ПерестроитьИспользованиеАгрегатов();
	
	ОбновитьФорму();
	Состояние(НСтр("ru ='Перестроение использования агрегатов завершено...'", "ru"));	
КонецПроцедуры

&НаКлиенте
Процедура РегламентноеПерестроениеПриИзменении(Элемент)
	ИспользоватьРегламентноеЗадание("ПерестроениеАгрегатовПродаж", РегламентноеПерестроение);
	ОбновитьФорму();	
КонецПроцедуры

&НаСервере
Функция ОпределитьОптимальныеАгрегаты()
	
	ОптимальныеАгрегаты = РегистрыНакопления.Продажи.ОпределитьОптимальныеАгрегаты();
	
	// Состояние определения оптимальных агрегатов.
	Если ОпределитьОптимальность(ОптимальныеАгрегаты.Агрегаты) Тогда
		 Оптимальность = НСтр("ru ='Оптимальные: '", "ru");	// Список агрегатов конфигурации может быть оптимальным.
	Иначе
		 Оптимальность = НСтр("ru ='Неоптимальные: '", "ru");	// Список агрегатов конфигурации не может быть оптимальным.
	КонецЕсли;
	
	Оптимальность = Оптимальность + ОптимальныеАгрегаты.ДатаПостроения 
		+ НСтр("ru ='. Эффект: '", "ru") 
		+ ОптимальныеАгрегаты.Эффект 
		+ НСтр("ru ='. Размер: '", "ru") 
		+ ОптимальныеАгрегаты.Размер 
		+ ".";
					
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("XML");
	
	ЗаписьXML = Новый ЗаписьXML();
	ЗаписьXML.ОткрытьФайл(ИмяВременногоФайла);
	ЗаписьXML.ЗаписатьОбъявлениеXML();
	СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОптимальныеАгрегаты);
	ЗаписьXML.Закрыть();
	
	Возврат ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяВременногоФайла), УникальныйИдентификатор);

КонецФункции

&НаКлиенте
Процедура ОпределитьОптимальные(Команда)
	Состояние(НСтр("ru ='Подождите!'", "ru") 
		+ Символы.ВК 
		+ НСтр("ru ='Выполняется определение оптимальных агрегатов...'", "ru"));	
	
	АдресВременногоХранилища = ОпределитьОптимальныеАгрегаты();
	
	ПолучитьФайл(АдресВременногоХранилища, "ОптимальныеАгрегаты.xml");
     	
	Состояние(НСтр("ru ='Определение оптимальных агрегатов завершено.'", "ru"));	
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	ОбновитьФорму();
КонецПроцедуры

// Определяет, может ли список агрегатов конфигурации быть оптимальным.
&НаСервере
Функция ОпределитьОптимальность(ОптимальныеАгрегаты)
	АгрегатыКонфиг = Метаданные.РегистрыНакопления.Продажи.Агрегаты;
	
	// Индексы агрегатов конфигурации, которые соответствуют оптимальным агрегатам.
	НайденныеАгрегаты = Новый Соответствие();
	
	// Для каждого оптимального агрегата должен быть соответствующий агрегат конфигурации.
	Для каждого ОптимальныйАгрегат из ОптимальныеАгрегаты Цикл
		Найден = Ложь;
		
		// Поиск агрегата с точным совпадением периодичности и измерений. 
		// Агрегат не должен быть в НайденныеАгрегаты.
		Для Конф = 0 по АгрегатыКонфиг.Количество() - 1 Цикл
			Если ОптимальныйАгрегат.Периодичность = АгрегатыКонфиг[Конф].Периодичность И
				 НайденныеАгрегаты[Конф] = Неопределено И
				 СовпадаютИзмеренияАгрегатов(ОптимальныйАгрегат, АгрегатыКонфиг[Конф]) Тогда
				 
				 // Пометка агрегата как зарезервированного.
				 НайденныеАгрегаты.Вставить(Конф, Истина);
				 Найден = Истина;
				 Прервать;
			КонецЕсли
		КонецЦикла;
		
		Если Найден Тогда
			Продолжить;
		КонецЕсли;
		
		// Если не найден - поиск агрегата с Авто периодичностью и точным совпадением измерений. 
		// Агрегат не должен быть в НайденныеАгрегаты.
		Для Конф = 0 по АгрегатыКонфиг.Количество() - 1 Цикл
			Если АгрегатыКонфиг[Конф].Периодичность = ПериодичностьАгрегатаРегистраНакопления.Авто И
				 НайденныеАгрегаты[Конф] = Неопределено И
				 СовпадаютИзмеренияАгрегатов(ОптимальныйАгрегат, АгрегатыКонфиг[Конф]) Тогда
				 
				 // Пометка агрегата как зарезервированного.
				 НайденныеАгрегаты.Вставить(Конф, Истина);
				 Найден = Истина;
				 Прервать;
			КонецЕсли
		КонецЦикла;
		
		Если НЕ Найден Тогда
			Возврат Ложь;
		КонецЕсли;
			
	КонецЦикла;
	
	Возврат Истина;
КонецФункции

// Проверяет, совпадают ли измерения у оптимального агрегата и агрегата из конфигурации.
&НаСервере
Функция СовпадаютИзмеренияАгрегатов(ОптимальныйАгрегат, АгрегатКонфиг)
	
	// Число измерений должно быть одинаковым.
	Если ОптимальныйАгрегат.Измерения.Количество() <> АгрегатКонфиг.Измерения.Количество() Тогда
		Возврат Ложь;
	КонецЕсли;
	
	// Для каждого измерения оптимального агрегата должно существовать такое же в агрегате конфигурации.
	Для каждого Агрегат из ОптимальныйАгрегат.Измерения Цикл
		Найдено = Ложь;
		
		// Поиск измерения в агрегате конфигурации.
		Для каждого Измерение из АгрегатКонфиг.Измерения Цикл
			Если Агрегат = Измерение.Имя Тогда
				Найдено = Истина;
				Прервать;
			КонецЕсли;
		КонецЦикла;
		
		Если НЕ Найдено Тогда
			Возврат Ложь;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Истина;
КонецФункции

